package com.mt.mtyx.common.utils.generate.context;

import com.mt.mtyx.common.utils.Helper;
import com.mt.mtyx.common.utils.generate.exception.VelocityException;
import com.mt.mtyx.common.utils.generate.generate.code.GenerateCondition;
import com.mt.mtyx.common.utils.generate.generate.code.GenerateMethod;
import com.mt.mtyx.common.utils.generate.generate.code.GenerateStandard;
import com.mt.mtyx.common.utils.generate.generate.code.GenerateType;
import com.mt.mtyx.common.utils.generate.generate.config.*;
import com.mt.mtyx.common.utils.generate.generate.table.FieldData;
import com.mt.mtyx.common.utils.generate.generate.table.TableData;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.stream.Collectors;

/**
 * @author WMT
 * @Date 2023/5/26 17:27
 */
public class FastAutoGenerateCode {

    private final DatabaseCodeConfig databaseCodeConfig;

    private final GlobalCodeConfig globalCodeConfig;

    private final PackingCodeConfig packingCodeConfig;

    private final EntityCodeConfig entityCodeConfig;

    private final MapperCodeConfig mapperCodeConfig;

    private final ServiceCodeConfig serviceCodeConfig;

    private final ControllerCodeConfig controllerCodeConfig;

    private final List<OtherCodeConfig> otherCodeConfig;

    private Consumer<GenerateStandard> consumer;

    private FastAutoGenerateCode(String username, String password, String url, String driver) {
        this.databaseCodeConfig = new DatabaseCodeConfig(username, password, url, driver);
        this.globalCodeConfig = new GlobalCodeConfig();
        this.packingCodeConfig = new PackingCodeConfig();
        this.entityCodeConfig = new EntityCodeConfig();
        this.mapperCodeConfig = new MapperCodeConfig();
        this.serviceCodeConfig = new ServiceCodeConfig();
        this.controllerCodeConfig = new ControllerCodeConfig();
        this.otherCodeConfig = new LinkedList<>();
    }

    public FastAutoGenerateCode global(Consumer<GlobalCodeConfig> builder) {
        builder.accept(this.globalCodeConfig);
        return this;
    }

    public FastAutoGenerateCode datasource(Consumer<DatabaseCodeConfig> builder) {
        builder.accept(this.databaseCodeConfig);
        return this;
    }

    public FastAutoGenerateCode packing(Consumer<PackingCodeConfig> builder) {
        builder.accept(this.packingCodeConfig);
        return this;
    }

    public FastAutoGenerateCode entity(Consumer<EntityCodeConfig> builder) {
        builder.accept(this.entityCodeConfig);
        return this;
    }

    public FastAutoGenerateCode mapper(Consumer<MapperCodeConfig> builder) {
        builder.accept(this.mapperCodeConfig);
        return this;
    }

    public FastAutoGenerateCode service(Consumer<ServiceCodeConfig> builder) {
        builder.accept(this.serviceCodeConfig);
        return this;
    }

    public FastAutoGenerateCode controller(Consumer<ControllerCodeConfig> builder) {
        builder.accept(this.controllerCodeConfig);
        return this;
    }

    public FastAutoGenerateCode other(Supplier<List<OtherCodeConfig>> supplier) {
        this.otherCodeConfig.addAll(supplier.get());
        return this;
    }

    public FastAutoGenerateCode consumer(Consumer<GenerateStandard> consumer) {
        this.consumer = consumer;
        return this;
    }


    public static FastAutoGenerateCode create(String username, String password, String url, String driver) {
        return new FastAutoGenerateCode(username, password, url, driver);
    }

    /**
     * 执行
     *
     * @return {@code FastAutoGenerateCode}
     */
    public FastAutoGenerateCode execute() {
        for (Map.Entry<String, TableData> entry : DisplayTableData.display(databaseCodeConfig).entrySet()) {
            GenerateStandard init = init(entry.getValue());
            if (consumer != null) consumer.accept(init);
            VelocityGenerate.useVelocity(init);
        }
//        Clipboard systemClipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
//        systemClipboard.setContents(new StringSelection(JSONUtil.parse(display).toStringPretty()), null);
        return this;
    }


    /**
     * 基础配置
     *
     * @param standard 标准
     */
    private void baseConfig(GenerateStandard standard) {
        standard.setGlobal(globalCodeConfig);
        standard.setPacking(packingCodeConfig);
        standard.setEntity(entityCodeConfig);
        standard.setMapper(mapperCodeConfig);
        standard.setService(serviceCodeConfig);
        standard.setController(controllerCodeConfig);
        standard.setOther(otherCodeConfig);
    }

    /**
     * 表配置
     *
     * @param tableData 表数据
     * @param standard  标准
     */
    private void tableConfig(TableData tableData, GenerateStandard standard) {
        String tableName = tableData.getTableName();
        standard.setTableName(tableName);
        String baseName = tableName;
        if (packingCodeConfig.getTablePrefixConvert() != null && !packingCodeConfig.getTablePrefixConvert().isEmpty()) {
            for (Map.Entry<String, String> entry : packingCodeConfig.getTablePrefixConvert().entrySet()) {
                if (baseName.startsWith(entry.getKey())) baseName = baseName.replace(entry.getKey(), entry.getValue());
            }
        }
        if (packingCodeConfig.getTableSuffixConvert() != null && !packingCodeConfig.getTableSuffixConvert().isEmpty()) {
            for (Map.Entry<String, String> entry : packingCodeConfig.getTableSuffixConvert().entrySet()) {
                if (baseName.endsWith(entry.getKey())) baseName = baseName.replace(entry.getKey(), entry.getValue());
            }
        }
        baseName = packingCodeConfig.getSeparator().to(packingCodeConfig.getFormat(), baseName);
        entityCodeConfig.entityName(String.format(entityCodeConfig.getEntityFormat(), baseName));
        mapperCodeConfig.mapperName(String.format(mapperCodeConfig.getMapperFormat(), baseName));
        mapperCodeConfig.mapperXmlName(String.format(mapperCodeConfig.getMapperXmlFormat(), baseName));
        serviceCodeConfig.serviceName(String.format(serviceCodeConfig.getServiceFormat(), baseName));
        serviceCodeConfig.serviceImplName(String.format(serviceCodeConfig.getServiceImplFormat(), baseName));
        controllerCodeConfig.controllerName(String.format(controllerCodeConfig.getControllerFormat(), baseName));
        for (OtherCodeConfig codeConfig : otherCodeConfig) {
            codeConfig.otherName(String.format(codeConfig.getOtherFormat(), baseName));
        }
        standard.setBaseName(baseName);
        standard.setComment(Helper.isEmpty(tableData.getTableComment()) ? baseName : tableData.getTableComment());
    }

    /**
     * 路径配置
     *
     * @param standard 标准
     */
    private void pathConfig(GenerateStandard standard) {
        String outDir = globalCodeConfig.getOutDir();
        String basePackage = packingCodeConfig.getBasePackage();
        Map<String, String> fileMap = new HashMap<>();
        Map<String, Boolean> generateConfig = globalCodeConfig.getGenerateConfig();
        if (generateConfig.containsKey("entity") && generateConfig.get("entity")) {
            fileMap.put("entity", createFile(outDir, basePackage, packingCodeConfig.getEntity(), entityCodeConfig.getEntityName()));
        }
        if (generateConfig.containsKey("mapper") && generateConfig.get("mapper")) {
            fileMap.put("mapper", createFile(outDir, basePackage, packingCodeConfig.getMapper(), mapperCodeConfig.getMapperName()));
        }
        if (generateConfig.containsKey("xml") && generateConfig.get("xml")) {
            fileMap.put("mapperXml", createMapper(outDir, packingCodeConfig.getMapperXml(), mapperCodeConfig.getMapperName()));
        }
        if (generateConfig.containsKey("service") && generateConfig.get("service")) {
            fileMap.put("service", createFile(outDir, basePackage, packingCodeConfig.getService(), serviceCodeConfig.getServiceName()));
        }
        if (generateConfig.containsKey("serviceImpl") && generateConfig.get("serviceImpl")) {
            fileMap.put("serviceImpl", createFile(outDir, basePackage, packingCodeConfig.getServiceImpl(), serviceCodeConfig.getServiceImplName()));
        }
        if (generateConfig.containsKey("controller") && generateConfig.get("controller")) {
            fileMap.put("controller", createFile(outDir, basePackage, packingCodeConfig.getController(), controllerCodeConfig.getControllerName()));
        }
        if (generateConfig.containsKey("other") && generateConfig.get("other")) {
            for (OtherCodeConfig codeConfig : otherCodeConfig) {
                fileMap.put(codeConfig.getOther(), createFile(outDir, basePackage, codeConfig.getOtherPack(), codeConfig.getOtherName()));
            }
        }
        standard.setFileMap(fileMap);
    }

    /**
     * 模板配置
     *
     * @param standard 标准
     */
    private void templateConfig(GenerateStandard standard) {
        Map<String, String> templates = new HashMap<>();
        // 获取模板 配置许可
        Map<String, Boolean> generateConfig = globalCodeConfig.getGenerateConfig();
        if (generateConfig.containsKey("entity") && generateConfig.get("entity")) {
            templates.put("entity", "/templates/entity.java.vm");
        }
        if (generateConfig.containsKey("mapper") && generateConfig.get("mapper")) {
            templates.put("mapper", "/templates/mapper.java.vm");
        }
        if (generateConfig.containsKey("xml") && generateConfig.get("xml")) {
            templates.put("mapperXml", "/templates/mapper.xml.vm");
        }
        if (generateConfig.containsKey("service") && generateConfig.get("service")) {
            templates.put("service", "/templates/service.java.vm");
        }
        if (generateConfig.containsKey("serviceImpl") && generateConfig.get("serviceImpl")) {
            templates.put("serviceImpl", "/templates/serviceImpl.java.vm");
        }
        if (generateConfig.containsKey("controller") && generateConfig.get("controller")) {
            templates.put("controller", "/templates/controller.java.vm");
        }
        if (generateConfig.containsKey("other") && generateConfig.get("other")) {
            for (OtherCodeConfig codeConfig : otherCodeConfig) {
                templates.put(codeConfig.getOther(), codeConfig.getTemplate());
            }
        }
        standard.setTemplate(templates);
    }

    /**
     * 字段配置
     *
     * @param tableData 表数据
     * @param standard  标准
     */
    private void fieldConfig(TableData tableData, GenerateStandard standard) {
        List<String> fieldsName = new LinkedList<>();
        List<FieldData> fields = tableData.getFields();
        List<FieldData> newFields = new LinkedList<>(fields);
        List<String> supperField = new LinkedList<>();
        Set<String> importPackage = new TreeSet<>(String::compareTo);
        if (Helper.isNotEmpty(entityCodeConfig.getSupperCLass())) {
            try {
                Class<?> clazz = Class.forName(entityCodeConfig.getSupperCLass());
                for (Field field : clazz.getDeclaredFields()) {
                    supperField.add(field.getName());
                }
                importPackage.add(entityCodeConfig.getSupperCLass());
            } catch (ClassNotFoundException e) {
                throw new VelocityException("父包名不存在！");
            }
        }
        // 过滤父类字段
        if (!supperField.isEmpty()) {
            for (FieldData field : fields) {
                Iterator<String> iterator = supperField.iterator();
                while (iterator.hasNext()) {
                    if (iterator.next().equalsIgnoreCase(field.getCapitalName())) {
                        newFields.remove(field);
                        break;
                    }
                }
            }
        }
        for (FieldData field : tableData.getFields()) {
            if (Helper.isEmpty(field.getComment())) field.setComment(field.getField());
            fieldsName.add(field.getField());
            if (field.getJavaTypePackage() != null
                    && !field.getJavaTypePackage().startsWith("java.lang")
                    && field.getJavaTypePackage().contains("."))
                importPackage.add(field.getJavaTypePackage());
        }
        entityCodeConfig.importPackage(importPackage);
        standard.setFieldsName(fieldsName);
        standard.setFields(newFields);
    }

    /**
     * 其他配置
     *
     * @param standard 标准
     */
    private void otherConfig(GenerateStandard standard) {
        mapperMethod();
        serviceMethod();
        serviceImplMethod();
        controllerMethod(standard.getComment());
        otherMethod(standard.getTableData());
    }

    /**
     * 其他方法
     */
    private void otherMethod(TableData tableData) {
        for (OtherCodeConfig codeConfig : otherCodeConfig) {
            List<String> supperField = new LinkedList<>();
            Set<String> otherImport = new TreeSet<>(String::compareTo);
            if (Helper.isNotEmpty(codeConfig.getSupperCLass())) {
                try {
                    Class<?> clazz = Class.forName(codeConfig.getSupperCLass());
                    for (Field field : clazz.getDeclaredFields()) {
                        supperField.add(field.getName());
                    }
                    otherImport.add(codeConfig.getSupperCLass());
                } catch (ClassNotFoundException e) {
                    throw new VelocityException("父包名不存在！");
                }
            }
            // 导包
            for (FieldData field : tableData.getFields()) {
                if (field.getJavaTypePackage() != null
                        && !field.getJavaTypePackage().startsWith("java.lang")
                        && field.getJavaTypePackage().contains("."))
                    otherImport.add(field.getJavaTypePackage());
            }
            codeConfig.importPackage(otherImport);
        }
    }

    /**
     * mapper方法
     */
    private void mapperMethod() {
        Set<String> mapperImport = new TreeSet<>(String::compareTo);
        Map<String, GenerateMethod> method = mapperCodeConfig.getMethod();
        for (Map.Entry<String, GenerateMethod> entry : method.entrySet()) {
            if (entry.getValue() == null) continue;
            String entityName = entityCodeConfig.getEntityName();
            if ("INSERT".equals(entry.getKey())) {
                String entity = packingCodeConfig.getBasePackage() + "." + packingCodeConfig.getEntity() + "." + entityCodeConfig.getEntityName();
                mapperCodeConfig.methodMap((data) -> {
                    GenerateMethod insert = data.get("INSERT");
                    insert.setMethodName(String.format(insert.getMethodFormat(), entityName));
                    insert.setMethodComment(String.format("添加%s对象", entityName));
                    insert.setReturnType("int");
                    insert.setReturnComment(String.format("添加%s的条数", entityName));
                    List<GenerateType> param = new LinkedList<>();
                    param.add(new GenerateType<Map<Integer, List<GenerateCondition>>>(entityName, entity, entityName + "对象", entityName, null, String.valueOf(entityName.charAt(0)).toLowerCase(Locale.ROOT) + entityName.substring(1)));
                    insert.setParam(param);
                });
            }
            if ("DELETE".equals(entry.getKey())) {
                mapperCodeConfig.methodMap((data) -> {
                    GenerateMethod delete = data.get("DELETE");
                    delete.setMethodName(String.format(delete.getMethodFormat(), entityName));
                    delete.setMethodComment(String.format("根据内码删除%s对象", entityName));
                    delete.setReturnType("int");
                    delete.setReturnComment(String.format("删除%s的条数", entityName));
                    List<GenerateType> param = new LinkedList<>();
                    param.add(new GenerateType<Map<Integer, List<GenerateCondition>>>("String", null, "内码", "String", null, "fId"));
                    delete.setParam(param);
                });
            }
            if ("UPDATE".equals(entry.getKey())) {
                String entity = packingCodeConfig.getBasePackage() + "." + packingCodeConfig.getEntity() + "." + entityCodeConfig.getEntityName();
                mapperCodeConfig.methodMap((data) -> {
                    GenerateMethod update = data.get("UPDATE");
                    update.setMethodName(String.format(update.getMethodFormat(), entityName));
                    update.setMethodComment(String.format("根据条件修改%s对象", entityName));
                    update.setReturnType("int");
                    update.setReturnComment(String.format("修改%s的条数", entityName));
                    List<GenerateType> param = new LinkedList<>();
                    param.add(new GenerateType<Map<Integer, List<GenerateCondition>>>(entityName, entity, entityName + "对象", entityName, null, String.valueOf(entityName.charAt(0)).toLowerCase(Locale.ROOT) + entityName.substring(1)));
                    update.setParam(param);
                });
            }
            if ("COUNT".equals(entry.getKey())) {
                mapperCodeConfig.methodMap((data) -> {
                    GenerateMethod count = data.get("COUNT");
                    count.setMethodName(String.format(count.getMethodFormat(), entityName));
                    count.setMethodComment(String.format("根据条件查询%s总数", entityName));
                    count.setReturnType("long");
                    count.setReturnComment(String.format("%s的总条数", entityName));
                    List<GenerateType> param = new LinkedList<>();
                    param.add(new GenerateType<Map<Integer, List<GenerateCondition>>>("Map<String,Object>", "java.util.Map", "查询条件", "Map", "long", null, "map"));
                    count.setParam(param);
                });
            }
            if ("LIST".equals(entry.getKey())) {
                String entity = packingCodeConfig.getBasePackage() + "." + packingCodeConfig.getEntity() + "." + entityCodeConfig.getEntityName();
                if (Helper.isEmpty(globalCodeConfig.getJsonPageCLass())) throw new VelocityException("分页类型不能为空！");
                mapperCodeConfig.methodMap((data) -> {
                    GenerateMethod list = data.get("LIST");
                    list.setMethodName(String.format(list.getMethodFormat(), entityName));
                    list.setMethodComment(String.format("条件分页查询%s", entityName));
                    String re = "List<" + entityName + ">";
//                    String re = jsonPage.substring(jsonPage.lastIndexOf(".") + 1) + "<" + entityName + ">";
                    list.setReturnType(re);
                    list.setReturnClass(Arrays.asList("java.util.List", entity));
                    list.setReturnComment(String.format("分页查询%s的结果集", entityName));
                    List<GenerateType> param = new LinkedList<>();
                    param.add(new GenerateType<Map<Integer, List<GenerateCondition>>>("Map<String,Object>", "java.util.Map", "查询条件", "Map", entityName, null, "map"));
                    list.setParam(param);
                });
            }
            if ("ONE".equals(entry.getKey())) {
                String entity = packingCodeConfig.getBasePackage() + "." + packingCodeConfig.getEntity() + "." + entityCodeConfig.getEntityName();
                mapperCodeConfig.methodMap((data) -> {
                    GenerateMethod one = data.get("ONE");
                    one.setMethodName(String.format(one.getMethodFormat(), entityName));
                    one.setMethodComment(String.format("根据内码查询%s对象", entityName));
                    one.setReturnType(entityName);
                    one.setReturnClass(Collections.singletonList(entity));
                    one.setReturnComment(String.format("查询到的%s对象", entityName));
                    List<GenerateType> param = new LinkedList<>();
                    param.add(new GenerateType<Map<Integer, List<GenerateCondition>>>("String", null, "内码", "String", entityName, null, "fId"));
                    one.setParam(param);
                });
            }
        }
        for (Map.Entry<String, GenerateMethod> entry : mapperCodeConfig.getMethod().entrySet()) {
            GenerateMethod generateMethod = entry.getValue();
            if (generateMethod == null) continue;
            List<String> returnClass = generateMethod.getReturnClass();
            List<GenerateType> param = generateMethod.getParam();
            if (returnClass != null && !returnClass.isEmpty()) {
                mapperImport.addAll(returnClass);
            }
            if (param != null && !param.isEmpty()) {
                mapperImport.addAll(param.stream().map(GenerateType::getClazz).filter(Helper::isNotEmpty).collect(Collectors.toList()));
            }
        }
        if (Helper.isNotEmpty(mapperCodeConfig.getSupperCLass())) {
            mapperImport.add(mapperCodeConfig.getSupperCLass());
        }
        if (!mapperCodeConfig.isEnableMapperPlus() && Helper.isNotEmpty(mapperCodeConfig.getSupperCLass())) {
            mapperImport.add(getCLassPackage(mapperCodeConfig.getSupperCLass()));
        }
        mapperCodeConfig.importPackage(mapperImport);
    }

    /**
     * service方法
     */
    private void serviceMethod() {
        Set<String> serviceImport = new TreeSet<>(String::compareTo);
        Map<String, GenerateMethod> method = serviceCodeConfig.getMethod();
        for (Map.Entry<String, GenerateMethod> entry : method.entrySet()) {
            if (entry.getValue() == null) continue;
            String entityName = entityCodeConfig.getEntityName();
            if ("INSERT".equals(entry.getKey())) {
                String entity = packingCodeConfig.getBasePackage() + "." + packingCodeConfig.getEntity() + "." + entityCodeConfig.getEntityName();
                serviceCodeConfig.methodMap((data) -> {
                    GenerateMethod insert = data.get("INSERT");
                    insert.setMethodName(String.format(insert.getMethodFormat(), entityName));
                    insert.setMethodComment(String.format("添加%s对象", entityName));
                    insert.setReturnType("int");
                    insert.setReturnComment(String.format("添加%s的条数", entityName));
                    List<GenerateType> param = new LinkedList<>();
                    param.add(new GenerateType<Map<Integer, List<GenerateCondition>>>(entityName, entity, entityName + "对象", entityName, null, String.valueOf(entityName.charAt(0)).toLowerCase(Locale.ROOT) + entityName.substring(1)));
                    insert.setParam(param);
                });
            }
            if ("DELETE".equals(entry.getKey())) {
                serviceCodeConfig.methodMap((data) -> {
                    GenerateMethod delete = data.get("DELETE");
                    delete.setMethodName(String.format(delete.getMethodFormat(), entityName));
                    delete.setMethodComment(String.format("根据内码删除%s对象", entityName));
                    delete.setReturnType("int");
                    delete.setReturnComment(String.format("删除%s的条数", entityName));
                    List<GenerateType> param = new LinkedList<>();
                    param.add(new GenerateType<Map<Integer, List<GenerateCondition>>>("String", null, "内码", "String", null, "fId"));
                    delete.setParam(param);
                });
            }
            if ("UPDATE".equals(entry.getKey())) {
                String entity = packingCodeConfig.getBasePackage() + "." + packingCodeConfig.getEntity() + "." + entityCodeConfig.getEntityName();
                serviceCodeConfig.methodMap((data) -> {
                    GenerateMethod update = data.get("UPDATE");
                    update.setMethodName(String.format(update.getMethodFormat(), entityName));
                    update.setMethodComment(String.format("根据条件修改%s对象", entityName));
                    update.setReturnType("int");
                    update.setReturnComment(String.format("修改%s的条数", entityName));
                    List<GenerateType> param = new LinkedList<>();
                    param.add(new GenerateType<Map<Integer, List<GenerateCondition>>>(entityName, entity, entityName + "对象", entityName, null, String.valueOf(entityName.charAt(0)).toLowerCase(Locale.ROOT) + entityName.substring(1)));
                    update.setParam(param);
                });
            }
            if ("COUNT".equals(entry.getKey())) {
                serviceCodeConfig.methodMap((data) -> {
                    GenerateMethod count = data.get("COUNT");
                    count.setMethodName(String.format(count.getMethodFormat(), entityName));
                    count.setMethodComment(String.format("根据条件查询%s总数", entityName));
                    count.setReturnType("long");
                    count.setReturnComment(String.format("%s的总条数", entityName));
                    List<GenerateType> param = new LinkedList<>();
                    param.add(new GenerateType<Map<Integer, List<GenerateCondition>>>("Map<String,Object>", "java.util.Map", "查询条件", "Map", "long", null, "map"));
                    count.setParam(param);
                });
            }
            if ("LIST".equals(entry.getKey())) {
                String entity = packingCodeConfig.getBasePackage() + "." + packingCodeConfig.getEntity() + "." + entityCodeConfig.getEntityName();
                if (Helper.isEmpty(globalCodeConfig.getJsonPageCLass())) throw new VelocityException("分页类型不能为空！");
                serviceCodeConfig.methodMap((data) -> {
                    GenerateMethod list = data.get("LIST");
                    list.setMethodName(String.format(list.getMethodFormat(), entityName));
                    list.setMethodComment(String.format("条件分页查询%s", entityName));
                    String jsonPage = globalCodeConfig.getJsonPageCLass();
                    String re = jsonPage.substring(jsonPage.lastIndexOf(".") + 1) + "<" + entityName + ">";
                    list.setReturnType(re);
                    list.setReturnClass(Arrays.asList(jsonPage, entity));
                    list.setReturnComment(String.format("分页查询%s的结果集", entityName));
                    List<GenerateType> param = new LinkedList<>();
                    param.add(new GenerateType<Map<Integer, List<GenerateCondition>>>("Map<String,Object>", "java.util.Map", "查询条件", "Map", entityName, null, "map"));
                    list.setParam(param);
                });
            }
            if ("ONE".equals(entry.getKey())) {
                String entity = packingCodeConfig.getBasePackage() + "." + packingCodeConfig.getEntity() + "." + entityCodeConfig.getEntityName();
                serviceCodeConfig.methodMap((data) -> {
                    GenerateMethod one = data.get("ONE");
                    one.setMethodName(String.format(one.getMethodFormat(), entityName));
                    one.setMethodComment(String.format("根据内码查询%s对象", entityName));
                    one.setReturnType(entityName);
                    one.setReturnClass(Collections.singletonList(entity));
                    one.setReturnComment(String.format("查询到的%s对象", entityName));
                    List<GenerateType> param = new LinkedList<>();
                    param.add(new GenerateType<Map<Integer, List<GenerateCondition>>>("String", null, "内码", "String", entityName, null, "fId"));
                    one.setParam(param);
                });
            }
        }
        for (Map.Entry<String, GenerateMethod> entry : serviceCodeConfig.getMethod().entrySet()) {
            GenerateMethod generateMethod = entry.getValue();
            if (generateMethod == null) continue;
            List<String> returnClass = generateMethod.getReturnClass();
            List<GenerateType> param = generateMethod.getParam();
            if (returnClass != null && !returnClass.isEmpty()) {
                serviceImport.addAll(returnClass);
            }
            if (param != null && !param.isEmpty()) {
                serviceImport.addAll(param.stream().map(GenerateType::getClazz).filter(Helper::isNotEmpty).collect(Collectors.toList()));
            }
        }
        if (Helper.isNotEmpty(serviceCodeConfig.getServiceSupperClass())) {
            serviceImport.add(serviceCodeConfig.getServiceSupperClass());
        }
        if (!serviceCodeConfig.isEnableMybatisPlus() && Helper.isNotEmpty(serviceCodeConfig.getServiceSupperClass())) {
            serviceImport.add(getCLassPackage(serviceCodeConfig.getServiceSupperClass()));
        }
        serviceCodeConfig.importServicePackage(serviceImport);
    }

    /**
     * service实现类方法
     */
    private void serviceImplMethod() {
        Set<String> serviceImplImport = new TreeSet<>(String::compareTo);
        serviceImplImport.addAll(serviceCodeConfig.getImportServicePackage());
        serviceImplImport.add(packingCodeConfig.getBasePackage() + "." + packingCodeConfig.getMapper() + "." + mapperCodeConfig.getMapperName());
        serviceImplImport.add(packingCodeConfig.getBasePackage() + "." + packingCodeConfig.getService() + "." + serviceCodeConfig.getServiceName());
        Set<String> set = serviceCodeConfig.getMethod().keySet();
        List<String> list = Arrays.asList("INSERT", "UPDATE", "DELETE");
        if (Helper.isNotEmpty(serviceCodeConfig.getServiceImplSupperClass())) {
            serviceImplImport.add(serviceCodeConfig.getServiceImplSupperClass());
        }
        if (serviceCodeConfig.isEnableMybatisPlus()) {
            serviceImplImport.add(packingCodeConfig.getBasePackage() + "." + packingCodeConfig.getMapper() + "." + mapperCodeConfig.getMapperName());
        }
        for (String method : set) {
            if ("LIST".equals(method)) {
                serviceImplImport.add("java.util.Collections");
            }
            if (list.contains(method)) {
                serviceImplImport.add("org.springframework.transaction.annotation.Transactional");
            }
        }
        serviceCodeConfig.importServiceImplPackage(serviceImplImport);
    }

    private void controllerMethod(String tableComment) {
        Set<String> controllerImport = new TreeSet<>(String::compareTo);
        Map<String, GenerateMethod> method = controllerCodeConfig.getMethod();
        for (Map.Entry<String, GenerateMethod> entry : method.entrySet()) {
            if (entry.getValue() == null) continue;
            String entityName = entityCodeConfig.getEntityName();
            String cm = Helper.isEmpty(tableComment) ? entityName : tableComment;
            final String comment = cm;
            if ("INSERT".equals(entry.getKey())) {
                String entity = packingCodeConfig.getBasePackage() + "." + packingCodeConfig.getEntity() + "." + entityCodeConfig.getEntityName();
                controllerCodeConfig.methodMap((data) -> {
                    GenerateMethod insert = data.get("INSERT");
                    insert.setMethodName(String.format(insert.getMethodFormat(), entityName));
                    insert.setMethodComment(String.format("添加%s对象", entityName));
                    insert.setReturnType("int");
                    insert.setReturnComment(String.format("新增%s", comment));
                    List<GenerateType> param = new LinkedList<>();
                    param.add(new GenerateType<Map<Integer, List<GenerateCondition>>>(entityName, entity, entityName + "对象", entityName, null, String.valueOf(entityName.charAt(0)).toLowerCase(Locale.ROOT) + entityName.substring(1)));
                    insert.setParam(param);
                });
            }
            if ("DELETE".equals(entry.getKey())) {
                controllerCodeConfig.methodMap((data) -> {
                    GenerateMethod delete = data.get("DELETE");
                    delete.setMethodName(String.format(delete.getMethodFormat(), entityName));
                    delete.setMethodComment(String.format("根据内码删除%s对象", entityName));
                    delete.setReturnType("int");
                    delete.setReturnComment(String.format("删除%s", comment));
                    List<GenerateType> param = new LinkedList<>();
                    param.add(new GenerateType<Map<Integer, List<GenerateCondition>>>("String", null, "内码", "String", null, "fId"));
                    delete.setParam(param);
                });
            }
            if ("UPDATE".equals(entry.getKey())) {
                String entity = packingCodeConfig.getBasePackage() + "." + packingCodeConfig.getEntity() + "." + entityCodeConfig.getEntityName();
                controllerCodeConfig.methodMap((data) -> {
                    GenerateMethod update = data.get("UPDATE");
                    update.setMethodName(String.format(update.getMethodFormat(), entityName));
                    update.setMethodComment(String.format("根据条件修改%s对象", entityName));
                    update.setReturnType("int");
                    update.setReturnComment(String.format("修改%s", comment));
                    List<GenerateType> param = new LinkedList<>();
                    param.add(new GenerateType<Map<Integer, List<GenerateCondition>>>(entityName, entity, entityName + "对象", entityName, null, String.valueOf(entityName.charAt(0)).toLowerCase(Locale.ROOT) + entityName.substring(1)));
                    update.setParam(param);
                });
            }
            if ("COUNT".equals(entry.getKey())) {
                controllerCodeConfig.methodMap((data) -> {
                    GenerateMethod count = data.get("COUNT");
                    count.setMethodName(String.format(count.getMethodFormat(), entityName));
                    count.setMethodComment(String.format("根据条件查询%s总数", entityName));
                    count.setReturnType("long");
                    count.setReturnComment(String.format("查询%s的总条数", comment));
                    List<GenerateType> param = new LinkedList<>();
                    param.add(new GenerateType<Map<Integer, List<GenerateCondition>>>("Map<String,Object>", "java.util.Map", "查询条件", "Map", "long", null, "map"));
                    count.setParam(param);
                });
            }
            if ("LIST".equals(entry.getKey())) {
                String entity = packingCodeConfig.getBasePackage() + "." + packingCodeConfig.getEntity() + "." + entityCodeConfig.getEntityName();
                if (Helper.isEmpty(globalCodeConfig.getJsonPageCLass())) throw new VelocityException("分页类型不能为空！");
                controllerCodeConfig.methodMap((data) -> {
                    GenerateMethod list = data.get("LIST");
                    list.setMethodName(String.format(list.getMethodFormat(), entityName));
                    list.setMethodComment(String.format("条件分页查询%s", entityName));
                    String jsonPage = globalCodeConfig.getJsonPageCLass();
                    String re = jsonPage.substring(jsonPage.lastIndexOf(".") + 1) + "<" + entityName + ">";
                    list.setReturnType(re);
                    list.setReturnClass(Arrays.asList(jsonPage, entity));
                    list.setReturnComment(String.format("分页查询%s", comment));
                    List<GenerateType> param = new LinkedList<>();
                    param.add(new GenerateType<Map<Integer, List<GenerateCondition>>>("Map<String,Object>", "java.util.Map", "查询条件", "Map", entityName, null, "map"));
                    list.setParam(param);
                });
            }
            if ("ONE".equals(entry.getKey())) {
                String entity = packingCodeConfig.getBasePackage() + "." + packingCodeConfig.getEntity() + "." + entityCodeConfig.getEntityName();
                controllerCodeConfig.methodMap((data) -> {
                    GenerateMethod one = data.get("ONE");
                    one.setMethodName(String.format(one.getMethodFormat(), entityName));
                    one.setMethodComment(String.format("根据内码查询%s对象", entityName));
                    one.setReturnType(entityName);
                    one.setReturnClass(Collections.singletonList(entity));
                    one.setReturnComment(String.format("根据条件查询%s信息", comment));
                    List<GenerateType> param = new LinkedList<>();
                    param.add(new GenerateType<Map<Integer, List<GenerateCondition>>>("String", null, "内码", "String", entityName, null, "fId"));
                    one.setParam(param);
                });
            }
        }
        List<String> list = Arrays.asList("DELETE", "ONE");
        for (Map.Entry<String, GenerateMethod> entry : controllerCodeConfig.getMethod().entrySet()) {
            GenerateMethod generateMethod = entry.getValue();
            if (generateMethod == null) continue;
            List<String> returnClass = generateMethod.getReturnClass();
            List<GenerateType> param = generateMethod.getParam();
            if (returnClass != null && !returnClass.isEmpty()) {
                controllerImport.addAll(returnClass);
            }
            if (list.contains(entry.getKey()))
                controllerImport.add("org.springframework.web.bind.annotation.PathVariable");
            if (param != null && !param.isEmpty()) {
                controllerImport.addAll(param.stream().map(GenerateType::getClazz).filter(Helper::isNotEmpty).collect(Collectors.toList()));
            }
        }
        controllerImport.add(packingCodeConfig.getBasePackage() + "." + packingCodeConfig.getService() + "." + serviceCodeConfig.getServiceName());
        controllerImport.add(serviceCodeConfig.getAutowired());
        if (globalCodeConfig.isEnableSwagger()) {
            controllerImport.add("io.swagger.annotations.ApiOperation");
            controllerImport.add("io.swagger.annotations.Api");
        }
        if (Helper.isNotEmpty(controllerCodeConfig.getSupperClass())) {
            controllerImport.add(controllerCodeConfig.getSupperClass());
        }
        controllerCodeConfig.importPackage(controllerImport);
    }

    /**
     * 获取类包
     *
     * @param pack 包
     * @return {@code String}
     */
    private String getCLassPackage(String pack) {
        try {
            Class<?> clazz = Class.forName(pack);
            return clazz.getName();
        } catch (ClassNotFoundException e) {
            throw new VelocityException("父包名不存在！");
        }
    }

    public GenerateStandard init(TableData tableData) {
        GenerateStandard standard = new GenerateStandard();
        standard.setTableData(tableData);
        /*================================表配置===============================*/
        tableConfig(tableData, standard);
        /*================================表配置===============================*/
        /*================================基础配置===============================*/
        baseConfig(standard);
        /*================================基础配置===============================*/
        /*================================字段设置===============================*/
        fieldConfig(tableData, standard);
        /*================================字段设置===============================*/
        /*================================其他设置===============================*/
        otherConfig(standard);
        /*================================其他设置===============================*/
        /*================================路径设置===============================*/
        pathConfig(standard);
        /*================================路径设置===============================*/
        /*================================模板设置===============================*/
        templateConfig(standard);
        /*================================模板设置===============================*/
        return standard;
    }

    private String createFile(String outDir, String basePack, String pack, String fileName) {
        if (!outDir.endsWith(File.separator)) outDir = outDir + File.separator;
        if (Helper.isNotEmpty(basePack)) basePack = basePack.replace(".", File.separator);
        return outDir + "src" + File.separator + "main" + File.separator + "java" + File.separator + basePack + File.separator + pack.replace(".", File.separator) + File.separator + fileName + ".java";
    }

    private String createMapper(String outDir, String fileName) {
        if (!outDir.endsWith(File.separator)) outDir = outDir + File.separator;
        return outDir + "src" + File.separator + "main" + File.separator + "resources" + File.separator + "mapper" + File.separator + fileName + ".xml";
    }

    private String createMapper(String outDir, String mapper, String fileName) {
        if (!outDir.endsWith(File.separator)) outDir = outDir + File.separator;
        return outDir + "src" + File.separator + "main" + File.separator + "resources" + File.separator + mapper + File.separator + fileName + ".xml";
    }

    /**
     * 打开文件
     */
    public void open() {
        if (!globalCodeConfig.isOpenOutDir()) return;
        String fileName = globalCodeConfig.getOutDir() + File.separator + "src" + File.separator +
                "main" + File.separator + "java" + File.separator + packingCodeConfig.getBasePackage().replace(".", File.separator);
        // 获取系统名称
        String osName = System.getProperty("os.name");
        // 打开下载的文件
        if (osName != null) {
            try {
                if (osName.contains("Mac")) {
                    // 打开文件
                    Runtime.getRuntime().exec("open " + fileName);
                } else if (osName.contains("Windows")) {
                    // 打开文件
                    Runtime.getRuntime().exec("cmd /c start " + fileName);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                System.out.println("open " + fileName);
            }
        }
    }

}
